<template>
  <div class="app-container">
    <!-- 顶部导航栏 -->
    <el-menu
      :default-active="activeIndex"
      class="el-menu-demo"
      mode="horizontal"
      @select="handleSelect"
    >
      <el-menu-item index="1" class="nav-item">
        <el-icon><HomeFilled /></el-icon>
        <span>主页</span>
      </el-menu-item>
      <el-menu-item index="2" class="nav-item">
        <el-icon><PictureFilled /></el-icon>
        <span>图片</span>
      </el-menu-item>
      <el-menu-item index="3" class="nav-item">
        <el-icon><VideoCameraFilled /></el-icon>
        <span>视频</span>
      </el-menu-item>
      <el-menu-item index="4" class="nav-item">
        <el-icon><UploadFilled /></el-icon>
        <span>上传</span>
      </el-menu-item>
    </el-menu>

    <!-- 顶部间距 -->
    <div class="h-6" />

    <!-- 视频标题 -->
    <div class="section-title">
      <el-icon><VideoCameraFilled /></el-icon>
      <span>我的视频</span>
    </div>

    <!-- 视频列表 -->
    <div class="video-list" v-loading="loading">
      <div v-if="videoList.length === 0" class="no-data">暂无视频数据</div>
      <div
        v-for="(video, idx) in videoList"
        :key="video.id"
        class="video-card"
        @mouseenter="handleVideoHover(idx)"
        @mouseleave="handleVideoLeave(idx)"
      >
        <div class="video-wrapper">
          <HlsVideo
            :src="video.url"
            ref="videoRefs"
            class="video-player"
            preload="metadata"
            muted
            playsinline
            @loadedmetadata="onVideoLoaded(idx, $event)"
            @loadeddata="handleVideoLoaded(idx, $event)"
            @error="handleVideoError(idx, $event)"
            @progress="handleVideoProgress(idx, $event)"
            @canplay="handleVideoCanPlay(idx, $event)"
          />
          <!-- 视频封面 -->
          <div class="video-cover">
            <img
              :src="video.coverImage || getDefaultCover(video.url)"
              class="cover-image"
              @error="handleThumbnailError(idx)"
              v-if="!videoErrorStates[idx]"
            />
            <!-- 默认封面 -->
            <div v-if="videoErrorStates[idx]" class="default-cover">
              <el-icon><VideoCameraFilled /></el-icon>
            </div>
          </div>
          <!-- 视频时长 -->
          <div class="video-duration">{{ videoDurations[idx] || "00:00" }}</div>
          <!-- 鼠标悬浮时显示播放按钮 -->
          <div
            v-if="hoverIndex === idx"
            class="video-overlay"
            @click="playVideo(idx)"
          >
            <div class="play-icon">
              <el-icon><VideoPlay /></el-icon>
            </div>
          </div>
          <!-- 加载状态 -->
          <div v-if="videoLoadingStates[idx]" class="video-loading">
            <el-icon class="is-loading"><Loading /></el-icon>
          </div>
          <!-- 错误状态 -->
          <div v-if="videoErrorStates[idx]" class="video-error">
            <el-icon><Warning /></el-icon>
            <span>加载失败</span>
          </div>
        </div>
        <div class="video-info">
          <div class="video-title">{{ video.title || "未命名视频" }}</div>
          <div class="video-stats">
            <span class="like-count" @click.stop="handleLike(video)">
              <el-icon :class="{ 'is-liked': video.isLiked }"><Star /></el-icon>
            </span>
            <span class="upload-time">{{ video.createdTime || "刚刚" }}</span>
          </div>
        </div>
      </div>
    </div>

    <!-- 分页 -->
    <div class="pagination-container">
      <el-pagination
        v-model:current-page="currentPage"
        v-model:page-size="pageSize"
        :page-sizes="[10, 20, 30, 50]"
        :background="true"
        :total="total"
        layout="total, sizes, prev, pager, next, jumper"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </div>

    <div
      v-if="showFullscreen"
      class="video-fullscreen-container"
      @click.self="closeFullscreen"
    >
      <HlsVideo
        v-if="fullscreenVideo && fullscreenVideo.url"
        :src="encodeURI(fullscreenVideo.url)"
        controls
        autoplay
        style="width: 80vw; height: 80vh; background: #000"
      />
      <button
        class="close-btn"
        @click="closeFullscreen"
        style="
          position: absolute;
          top: 20px;
          right: 40px;
          font-size: 32px;
          color: #fff;
          background: none;
          border: none;
          z-index: 10;
          cursor: pointer;
        "
      >
        ×
      </button>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted, nextTick, onUnmounted } from "vue";
import { useRouter } from "vue-router";
import { ElMessage } from "element-plus";
import {
  PictureFilled,
  VideoCameraFilled,
  HomeFilled,
  UploadFilled,
  View,
  Loading,
  Warning,
  VideoPlay,
  Star,
} from "@element-plus/icons-vue";
import {
  getUserVideosService,
  likeVideoService,
  unlikeVideoService,
} from "@/api/video";
import HlsVideo from "@/components/HlsVideo.vue";

interface ApiResponse<T> {
  code: number;
  message: string;
  data: T;
}

interface VideoListResponse {
  records: Array<{
    id: number;
    type: string;
    title: string;
    url: string;
    description: string;
    createdTime: string;
    updatedTime: string;
    creatorId: number;
    deleted: boolean;
    isBanner: boolean;
    liked: boolean;
    likeCount: number;
  }>;
  total: number;
  size: number;
  current: number;
  pages: number;
}

interface VideoItem {
  id: number;
  type: string;
  title: string;
  url: string;
  description: string;
  createdTime: string;
  updatedTime: string;
  creatorId: number;
  deleted: boolean;
  isBanner: boolean;
  coverImage?: string;
  isLiked?: boolean;
  likeCount?: number;
}

const router = useRouter();
const activeIndex = ref("3");
const loading = ref(false);
const videoList = ref<VideoItem[]>([]);
const currentPage = ref(1);
const pageSize = ref(10);
const total = ref(0);
const hoverIndex = ref<number | null>(null);
const videoRefs = ref<HTMLVideoElement[]>([]);
const videoDurations = ref<string[]>([]);
const videoCovers = ref<Map<number, HTMLCanvasElement>>(new Map());
const videoLoadQueue = ref<Map<number, boolean>>(new Map());
const hasCoverImage = ref<Record<number, boolean>>({});
const videoLoadingStates = ref<Record<number, boolean>>({});
const videoErrorStates = ref<Record<number, boolean>>({});
const videoLoadProgress = ref<Record<number, number>>({});
const visibleVideos = ref<Set<number>>(new Set());
const observer = ref<IntersectionObserver | null>(null);
const isMobile = ref(false);
const fullscreenVideo = ref<VideoItem | null>(null);
const showFullscreen = ref(false);

const handleSelect = (key: string) => {
  switch (key) {
    case "1":
      router.push("/daily");
      break;
    case "2":
      router.push("/picture");
      break;
    case "3":
      router.push("/video");
      break;
    case "4":
      router.push("/upload");
      break;
  }
};

const formatDuration = (seconds: number): string => {
  const minutes = Math.floor(seconds / 60);
  const remainingSeconds = Math.floor(seconds % 60);
  return `${minutes.toString().padStart(2, "0")}:${remainingSeconds
    .toString()
    .padStart(2, "0")}`;
};

const setVideoCoverRef = (el: HTMLCanvasElement | null, index: number) => {
  if (el) {
    videoCovers.value.set(index, el);
    if (videoLoadQueue.value.get(index)) {
      captureFirstFrame(index);
    }
  } else {
    videoCovers.value.delete(index);
  }
};

const handleVideoLoaded = (index: number, event: Event) => {
  try {
    const video = event.target as HTMLVideoElement;
    videoLoadingStates.value[index] = false;
    videoErrorStates.value[index] = false;
    videoLoadProgress.value[index] = 100;

    // 设置视频当前时间为0，确保从第一帧开始
    video.currentTime = 0;

    // 等待视频可以播放时捕获第一帧
    video.addEventListener(
      "canplay",
      () => {
        captureFirstFrame(index);
      },
      { once: true }
    );
  } catch (error) {
    console.error("处理视频加载完成事件失败:", error);
  }
};

const captureFirstFrame = (index: number) => {
  try {
    const video = videoRefs.value[index];
    const canvas = videoCovers.value.get(index);

    if (!video || !canvas) {
      console.warn("视频或Canvas元素未找到:", {
        video: !!video,
        canvas: !!canvas,
        index,
      });
      return;
    }

    // 确保视频已经加载并且可以播放
    if (video.readyState < 2) {
      console.warn("视频未准备好:", video.readyState);
      return;
    }

    const aspectRatio = video.videoWidth / video.videoHeight;
    let width = video.videoWidth || 640;
    let height = video.videoHeight || 360;

    const maxWidth = isMobile.value ? 320 : 640;
    const maxHeight = isMobile.value ? 180 : 360;

    if (width > maxWidth) {
      width = maxWidth;
      height = width / aspectRatio;
    }
    if (height > maxHeight) {
      height = maxHeight;
      width = height * aspectRatio;
    }

    canvas.width = width;
    canvas.height = height;

    const ctx = canvas.getContext("2d");
    if (ctx) {
      ctx.drawImage(video, 0, 0, width, height);
      hasCoverImage.value[index] = true;
      videoLoadQueue.value.delete(index);

      // 重置视频状态
      video.pause();
      video.currentTime = 0;
    }
  } catch (error) {
    console.error("捕获视频第一帧失败:", error);
  }
};

const getVideoList = async () => {
  loading.value = true;
  try {
    const res = await getUserVideosService({
      current: currentPage.value,
      size: pageSize.value,
    });
    const response = res as unknown as ApiResponse<VideoListResponse>;
    if (response.code === 0) {
      videoList.value = response.data.records.map((video) => ({
        ...video,
        isLiked: video.liked,
      }));
      total.value = response.data.total;
    } else {
      console.error("获取视频列表失败:", response.message);
      ElMessage.error(response.message || "获取视频列表失败");
    }
  } catch (error) {
    console.error("获取视频列表失败:", error);
    ElMessage.error("获取视频列表失败");
  } finally {
    loading.value = false;
  }
};

const onVideoLoaded = (index: number, event: Event) => {
  try {
    const video = event.target as HTMLVideoElement;
    videoDurations.value[index] = formatDuration(video.duration);
    videoLoadingStates.value[index] = false;
    videoErrorStates.value[index] = false;
    videoLoadProgress.value[index] = 100;
  } catch (error) {
    console.error("处理视频加载完成事件失败:", error);
  }
};

const isVideoVisible = (index: number) => {
  if (isMobile.value) {
    return hoverIndex.value === index;
  }
  return visibleVideos.value.has(index);
};

const checkMobile = () => {
  isMobile.value = window.innerWidth <= 768;
};

const handleVideoHover = (index: number) => {
  try {
    hoverIndex.value = index;
    if (!isMobile.value) {
      if (!visibleVideos.value.has(index)) {
        visibleVideos.value.add(index);
      }
    } else {
      const video = videoRefs.value[index];
      if (video) {
        video.play().catch((error) => {
          console.error("视频播放失败:", error);
        });
      }
    }
  } catch (error) {
    console.error("处理视频悬浮事件失败:", error);
  }
};

const handleVideoLeave = (index: number) => {
  try {
    hoverIndex.value = null;
    if (isMobile.value) {
      const video = videoRefs.value[index];
      if (video) {
        video.pause();
        video.currentTime = 0;
      }
    }
  } catch (error) {
    console.error("处理视频离开事件失败:", error);
  }
};

const initIntersectionObserver = () => {
  observer.value = new IntersectionObserver(
    (entries) => {
      entries.forEach((entry) => {
        const index = parseInt(entry.target.getAttribute("data-index") || "0");
        if (entry.isIntersecting) {
          visibleVideos.value.add(index);
        } else {
          visibleVideos.value.delete(index);
        }
      });
    },
    {
      rootMargin: "50px 0px",
      threshold: 0.1,
    }
  );
};

const handleVideoError = (index: number, event: Event) => {
  const video = event.target as HTMLVideoElement;
  videoLoadingStates.value[index] = false;
  videoErrorStates.value[index] = true;
  videoLoadProgress.value[index] = 0;

  console.error("视频加载错误:", {
    error: video.error,
    src: video.src,
    index,
  });

  if (video.error?.code === 4) {
    return;
  }

  if (video.error) {
    let errorMessage = "视频加载失败";
    switch (video.error.code) {
      case 1:
        errorMessage = "视频加载被中断";
        break;
      case 2:
        errorMessage = "网络错误，请检查网络连接";
        break;
      case 3:
        errorMessage = "视频解码失败，格式可能不支持";
        break;
      case 4:
        errorMessage = "视频格式不支持";
        break;
    }
    ElMessage.error(errorMessage);
  }
};

const handleVideoProgress = (index: number, event: Event) => {
  const video = event.target as HTMLVideoElement;
  if (video.buffered.length > 0) {
    const bufferedEnd = video.buffered.end(video.buffered.length - 1);
    const duration = video.duration;
    const progress = (bufferedEnd / duration) * 100;
    videoLoadProgress.value[index] = progress;
  }
};

const handleVideoCanPlay = (index: number, event: Event) => {
  const video = event.target as HTMLVideoElement;
  videoLoadingStates.value[index] = false;
  videoErrorStates.value[index] = false;
};

const playVideo = (index: number) => {
  fullscreenVideo.value = videoList.value[index];
  showFullscreen.value = true;
};

const closeFullscreen = () => {
  showFullscreen.value = false;
  fullscreenVideo.value = null;
};

const handleSizeChange = (val: number) => {
  pageSize.value = val;
  getVideoList();
};

const handleCurrentChange = (val: number) => {
  currentPage.value = val;
  getVideoList();
};

// 获取默认封面
const getDefaultCover = (videoUrl: string) => {
  // 如果视频URL是完整的URL，则替换为默认封面URL
  if (videoUrl.startsWith("http")) {
    return videoUrl.replace(/\.[^/.]+$/, "_thumb.jpg");
  }
  return videoUrl;
};

// 处理缩略图加载错误
const handleThumbnailError = (index: number) => {
  videoErrorStates.value[index] = true;
};

// 处理喜欢
const handleLike = async (video: {
  id: number;
  isLiked?: boolean;
  likeCount?: number;
}) => {
  try {
    const data = {
      mediaId: video.id,
      mediaType: "video",
    };

    if (video.isLiked) {
      const response = (await unlikeVideoService(
        data
      )) as unknown as ApiResponse<string>;
      if (response.code === 0) {
        video.isLiked = false;
        video.likeCount = (video.likeCount || 0) - 1;
        ElMessage.success(response.data || "已取消喜欢");
      } else {
        ElMessage.error(response.message || "取消喜欢失败");
      }
    } else {
      const response = (await likeVideoService(
        data
      )) as unknown as ApiResponse<string>;
      if (response.code === 0) {
        video.isLiked = true;
        video.likeCount = (video.likeCount || 0) + 1;
        ElMessage.success(response.data || "已添加到喜欢");
      } else {
        ElMessage.error(response.message || "添加喜欢失败");
      }
    }
  } catch (error) {
    console.error("操作失败:", error);
    ElMessage.error("操作失败，请稍后重试");
  }
};

onMounted(async () => {
  loading.value = true;
  initIntersectionObserver();
  await getVideoList();
  checkMobile();
  window.addEventListener("resize", checkMobile);
  loading.value = false;
});

onUnmounted(() => {
  observer.value?.disconnect();
  videoRefs.value.forEach((video) => {
    video.pause();
    video.src = "";
    video.load();
  });
  videoCovers.value.clear();
  videoLoadQueue.value.clear();
  window.removeEventListener("resize", checkMobile);
});
</script>

<style scoped>
.app-container {
  min-height: 100vh;
  padding-bottom: 40px;
  background: #f5f7fa;
}

.el-menu--horizontal {
  justify-content: center;
  background: #ffffff;
  border-radius: 8px;
  padding: 0 20px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
  border-bottom: none !important;
}

.nav-item {
  position: relative;
  padding: 0 16px;
  color: #303133;
  transition: all 0.3s ease;
}

.nav-item span {
  font-weight: 500;
  font-size: 16px;
  transition: color 0.3s ease;
}

.nav-item .el-icon {
  margin-right: 8px;
  color: #303133;
  transition: transform 0.3s ease, color 0.3s ease;
}

.nav-item:hover,
.nav-item.is-active {
  color: #409eff;
}

.nav-item:hover .el-icon,
.nav-item.is-active .el-icon {
  color: #409eff;
  transform: scale(1.1);
}

.section-title {
  position: relative;
  font-size: 22px;
  font-weight: 600;
  color: #303133;
  margin: 40px 0 20px;
  padding-left: 12px;
  border-left: 4px solid #409eff;
  display: flex;
  align-items: center;
  gap: 8px;
}

.section-title .el-icon {
  font-size: 24px;
  color: #409eff;
}

.video-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 20px;
  padding: 0 20px;
  max-width: 1200px;
  margin: 0 auto;
}

.video-card {
  background: #fff;
  border-radius: 8px;
  overflow: hidden;
  transition: transform 0.3s ease;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  position: relative;
}

.video-card:hover {
  transform: translateY(-5px);
}

.video-wrapper {
  position: relative;
  width: 100%;
  padding-top: 56.25%;
  background: #000;
}

.video-player {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.video-player::-webkit-media-controls {
  display: flex !important;
  opacity: 1 !important;
}

.video-duration {
  position: absolute;
  bottom: 8px;
  right: 8px;
  background: rgba(0, 0, 0, 0.7);
  color: #fff;
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 12px;
  z-index: 2;
}

.video-cover {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: #000;
  z-index: 1;
  display: flex;
  justify-content: center;
  align-items: center;
}

.cover-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #000;
}

.default-cover {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  background: #1a1a1a;
  color: #666;
}

.default-cover .el-icon {
  font-size: 48px;
}

.video-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.2);
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  transition: background 0.3s ease;
  z-index: 2;
  opacity: 0;
}

.video-card:hover .video-overlay {
  opacity: 1;
  background: rgba(0, 0, 0, 0.3);
}

.play-icon {
  width: 50px;
  height: 50px;
  background: rgba(0, 0, 0, 0.6);
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #fff;
  font-size: 24px;
  transition: transform 0.3s ease;
}

.video-overlay:hover .play-icon {
  transform: scale(1.1);
}

.play-icon .el-icon {
  font-size: 24px;
}

.video-info {
  padding: 8px;
  position: relative;
  z-index: 1;
}

.video-title {
  font-size: 14px;
  font-weight: 500;
  color: #18191c;
  margin-bottom: 8px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  line-height: 1.4;
}

.video-stats {
  display: flex;
  align-items: center;
  gap: 12px;
  color: #9499a0;
  font-size: 12px;
}

.play-count {
  display: flex;
  align-items: center;
  gap: 4px;
}

.play-count .el-icon {
  font-size: 14px;
}

.like-count {
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all 0.3s ease;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.1);
}

.like-count:hover {
  color: #f56c6c;
  background: rgba(245, 108, 108, 0.1);
}

.like-count .el-icon {
  font-size: 16px;
  transition: all 0.3s ease;
}

.like-count .is-liked {
  color: #f56c6c;
  transform: scale(1.1);
  background: rgba(245, 108, 108, 0.1);
}

.video-loading {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 3;
  color: #fff;
  font-size: 24px;
}

.video-error {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 3;
  color: #f56c6c;
  font-size: 14px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.video-error .el-icon {
  font-size: 24px;
}

.pagination-container {
  display: flex;
  justify-content: center;
  margin-top: 30px;
}

/* 响应式布局 */
@media screen and (max-width: 768px) {
  .video-list {
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 15px;
    padding: 0 15px;
  }

  .video-wrapper {
    padding-top: 56.25%;
  }

  .play-icon {
    width: 40px;
    height: 40px;
    font-size: 20px;
  }

  .default-cover .el-icon {
    font-size: 36px;
  }

  .video-card {
    touch-action: manipulation;
  }
}

/* 暗色模式支持 */
@media (prefers-color-scheme: dark) {
  .video-card {
    background: #1a1a1a;
  }

  .video-title {
    color: #e0e0e0;
  }

  .video-stats {
    color: #a0a0a0;
  }
}

.video-loading-progress {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  z-index: 3;
}

.video-error-state {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 3;
  color: #f56c6c;
  font-size: 14px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  background: rgba(0, 0, 0, 0.7);
  padding: 12px;
  border-radius: 4px;
}

.video-error-state .el-icon {
  font-size: 24px;
}

.video-fullscreen-container {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: rgba(0, 0, 0, 0.9);
  z-index: 9999;
  display: flex;
  justify-content: center;
  align-items: center;
  backdrop-filter: blur(5px);
}
</style>
